package com.meiyuetao.myt.partner.entity;

import java.math.BigDecimal;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import lab.s2jh.core.annotation.MetaData;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.envers.NotAudited;
import org.hibernate.validator.constraints.Email;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Lists;
import com.meiyuetao.myt.core.constant.GenericSexEnum;
import com.meiyuetao.myt.core.entity.MytBaseEntity;
import com.meiyuetao.myt.md.entity.Region;
import com.meiyuetao.myt.sale.entity.BoxOrder.OrderFromEnum;

@Entity
@Table(name = "iyb_partner")
@MetaData(value = "第三方合作伙伴")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
public class Partner extends MytBaseEntity implements Comparable<Partner> {
    private static final long serialVersionUID = 1L;
    public static final String MYT_CODE = "0000000000";
    @MetaData("代码")
    private String code;
    @MetaData("名称")
    private String abbr;
    @MetaData("地址")
    private String address;
    @MetaData("经度")
    private BigDecimal longitude;
    @MetaData("纬度")
    private BigDecimal latitude;
    @MetaData("网址")
    private String website;
    @MetaData("公司名")
    private String companyName;
    @MetaData("联系人")
    private String contactPerson;
    @MetaData("联系电话")
    private String contactPhone;
    @MetaData("联系邮箱")
    private String contactEmail;
    @MetaData("邮编")
    private String postCode;
    @MetaData("联系人性别")
    private GenericSexEnum contactSex = GenericSexEnum.U;
    @MetaData("即时通讯账号")
    private String contactIm;
    @MetaData("即时通讯账号类型")
    private String contactImType;
    @MetaData("备注")
    private String adminMemo;
    @MetaData("系统备注")
    private String sysMemo;
    @MetaData(value = "关联订单来源集合", comments = "以逗号分隔存储OrderFromEnum集合")
    private String grantedOrderFroms;

    @MetaData(value = "父节点")
    private Partner parent;

    @MetaData(value = "所属区域")
    private Region region;
    @MetaData(value = "类型")
    private PartnerTypeEnum partnerType;

    @MetaData("经纬度")
    private String latLon;

    List<PartnerR2Brand> partnerR2Brands = Lists.newArrayList();
    List<PartnerR2Commodity> partnerR2Commodities = Lists.newArrayList();

    public enum PartnerTypeEnum {
        @MetaData("库房地")
        STOCK,

        @MetaData("代理商")
        AGENT;
    }

    @Column(length = 32, unique = true, nullable = false)
    @JsonProperty
    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    @Column(length = 16)
    @JsonProperty
    public String getPostCode() {
        return postCode;
    }

    public void setPostCode(String postCode) {
        this.postCode = postCode;
    }

    @Column(nullable = false, length = 32)
    @JsonProperty
    public String getAbbr() {
        return abbr;
    }

    public void setAbbr(String abbr) {
        this.abbr = abbr;
    }

    @Column(length = 128)
    @JsonProperty
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Column(length = 128)
    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    @Column(length = 128)
    @JsonProperty
    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }

    @Column(length = 32)
    @JsonProperty
    public String getContactPerson() {
        return contactPerson;
    }

    public void setContactPerson(String contactPerson) {
        this.contactPerson = contactPerson;
    }

    @Column(length = 32)
    @JsonProperty
    public String getContactPhone() {
        return contactPhone;
    }

    public void setContactPhone(String contactPhone) {
        this.contactPhone = contactPhone;
    }

    @Column(length = 32)
    @Email
    public String getContactEmail() {
        return contactEmail;
    }

    public void setContactEmail(String contactEmail) {
        this.contactEmail = contactEmail;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 1)
    @JsonProperty
    public GenericSexEnum getContactSex() {
        return contactSex;
    }

    public void setContactSex(GenericSexEnum contactSex) {
        this.contactSex = contactSex;
    }

    @Column(length = 32)
    public String getContactIm() {
        return contactIm;
    }

    public void setContactIm(String contactIm) {
        this.contactIm = contactIm;
    }

    @Column(length = 512)
    public String getAdminMemo() {
        return adminMemo;
    }

    public void setAdminMemo(String adminMemo) {
        this.adminMemo = adminMemo;
    }

    @Column(length = 512)
    public String getSysMemo() {
        return sysMemo;
    }

    public void setSysMemo(String sysMemo) {
        this.sysMemo = sysMemo;
    }

    @Column(length = 32)
    public String getContactImType() {
        return contactImType;
    }

    public void setContactImType(String contactImType) {
        this.contactImType = contactImType;
    }

    @Transient
    @JsonIgnore
    public List<OrderFromEnum> buildGrantedOrderFromEnums() {
        if (StringUtils.isBlank(grantedOrderFroms)) {
            return null;
        }
        List<OrderFromEnum> orderFroms = Lists.newArrayList();
        String[] splits = grantedOrderFroms.split(",");
        for (String r2 : splits) {
            orderFroms.add(Enum.valueOf(OrderFromEnum.class, r2.trim()));
        }
        return orderFroms;
    }

    @Transient
    @JsonProperty
    public List<String> getSelectedGrantedOrderFroms() {
        if (StringUtils.isBlank(grantedOrderFroms)) {
            return null;
        }
        List<String> orderFroms = Lists.newArrayList();
        String[] splits = grantedOrderFroms.split(",");
        for (String r2 : splits) {
            orderFroms.add(r2.trim());
        }
        return orderFroms;
    }

    @Transient
    public String getDisplay() {
        return this.code + " " + this.abbr;
    }

    public String getGrantedOrderFroms() {
        return grantedOrderFroms;
    }

    public void setGrantedOrderFroms(String grantedOrderFroms) {
        this.grantedOrderFroms = grantedOrderFroms;
    }

    @ManyToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "PARENT_ID")
    @JsonIgnore
    public Partner getParent() {
        return parent;
    }

    public void setParent(Partner parent) {
        this.parent = parent;
    }

    @ManyToOne(cascade = CascadeType.DETACH)
    @JoinColumn(name = "region_sid", nullable = true)
    @JsonProperty
    public Region getRegion() {
        return region;
    }

    public void setRegion(Region region) {
        this.region = region;
    }

    @Enumerated(EnumType.STRING)
    @Column(length = 16)
    @JsonProperty
    public PartnerTypeEnum getPartnerType() {
        return partnerType;
    }

    public void setPartnerType(PartnerTypeEnum partnerType) {
        this.partnerType = partnerType;
    }

    @Override
    public int compareTo(Partner o) {
        return this.getCode().compareTo(o.getCode());
    }

    @Column(precision = 18, scale = 9)
    public BigDecimal getLongitude() {
        return longitude;
    }

    public void setLongitude(BigDecimal longitude) {
        this.longitude = longitude;
    }

    @Column(precision = 18, scale = 9)
    public BigDecimal getLatitude() {
        return latitude;
    }

    public void setLatitude(BigDecimal latitude) {
        this.latitude = latitude;
    }

    @OneToMany(mappedBy = "partner", cascade = CascadeType.ALL, orphanRemoval = true)
    @NotAudited
    @JsonIgnore
    public List<PartnerR2Brand> getPartnerR2Brands() {
        return partnerR2Brands;
    }

    public void setPartnerR2Brands(List<PartnerR2Brand> partnerR2Brands) {
        this.partnerR2Brands = partnerR2Brands;
    }

    @OneToMany(mappedBy = "partner", cascade = CascadeType.ALL, orphanRemoval = true)
    @NotAudited
    @JsonIgnore
    public List<PartnerR2Commodity> getPartnerR2Commodities() {
        return partnerR2Commodities;
    }

    public void setPartnerR2Commodities(List<PartnerR2Commodity> partnerR2Commodities) {
        this.partnerR2Commodities = partnerR2Commodities;
    }

    /**
     * 计算节点所在层级，根节点以0开始
     * 
     * @return
     */
    @Transient
    @JsonIgnore
    public int getLevel() {
        int level = 0;
        return loopLevel(level, this);
    }

    private int loopLevel(int level, Partner item) {
        Partner parent = item.getParent();
        if (parent != null && parent.getId() != null) {
            return loopLevel(level + 1, item.getParent());
        }
        return level;
    }

    public String getLatLon() {
        return latLon;
    }

    public void setLatLon(String latLon) {
        this.latLon = latLon;
    }

}